package CrowdCountingMVC.CCModel.Task.PythonScriptTask;

import CrowdCounting.Model.Util;
import CrowdCountingMVC.ExceptionInfo.InputException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

public class PythonRunTask implements Runnable {

    private ArrayList<String> cmdList;
    private Process process;
    private boolean isBufferOut;

    public PythonRunTask(boolean isBufferOut) {
        this.isBufferOut = isBufferOut;
        setBaseCmdParam();
    }

    public ArrayList<String> getCmdList() {
        return cmdList;
    }

    public void setBaseCmdParam() {
        cmdList = new ArrayList<>();
        cmdList.add(Util.loadProperty("pythonInterpreter"));
        if (isBufferOut) cmdList.add("-u");
        cmdList.add(Util.loadProperty("pythonScriptPath"));
        setConfigParam();
    }

    public void addInputValueToCmd(String value) {
        cmdList.add(value);
        System.out.println("命令行添加参数:" + value);
    }

    public void setConfigParam(){
        cmdList.add(Util.loadProperty("distance"));
        cmdList.add(Util.loadProperty("sigma_factor"));
        cmdList.add(Util.loadProperty("minimum_area_factor"));
    }

    public void setCmdInputParam() throws InputException {
        int rightCmdLength = cmdList.size() + (isBufferOut ? 0 : 1);
        if (rightCmdLength < 6) {
            Util.logger(Level.WARNING, "lack necessary parament for python script running");
            throw new InputException("请查看Python解释器和脚本路径");
        }
        if (rightCmdLength == 6) {
            cmdList.add(Util.loadProperty("segmentSize"));
            cmdList.add(Util.loadProperty("threshold"));
        }
        Util.logger(Level.INFO, cmdList.toString());
    }

    public Process getProcess() {
        return process;
    }

    public boolean getIsBufferOut() {
        return isBufferOut;
    }

    @Override
    public void run() {
        try {
            setCmdInputParam();
        } catch (InputException e) {
            e.printStackTrace();
        }
        process = runPythonScript(cmdList);
        checkErrorInfo();
    }

    public Process runPythonScript(String pythonInterpreterPath, String pythonScriptFilePath) {
        try {
            String[] cmd = {pythonInterpreterPath, pythonScriptFilePath};
            Process process = Runtime.getRuntime().exec(cmd);
            return process;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Process runPythonScript(ArrayList<String> cmdList) {
        try {
            String[] cmd = cmdList.toArray(new String[0]);
            Process process = Runtime.getRuntime().exec(cmd);
            return process;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void endPythonScript() {
        try {
            while (isAlive() || !process.waitFor(1, TimeUnit.SECONDS)) {
                process.destroy();
            }
            System.out.println("python脚本退出码： " + process.exitValue());
            System.out.println("python程序中止");
        } catch (InterruptedException e1) {
            throw new RuntimeException("python程序中止失败");
        }
    }

    public void checkErrorInfo() {
        try {
            BufferedReader isError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "gbk"));
            String lineErr;
            while ((lineErr = isError.readLine()) != null) {
                Util.logger(Level.WARNING, lineErr);
                System.out.println(lineErr);
            }
            isError.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void getInfo(Process process) {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            String lineErr;
            while ((lineErr = in.readLine()) != null) {
                System.out.println(lineErr);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isAlive() {
        if (process == null) return false;
        return process.isAlive();
    }
}
